namespace System.Security.Cryptography;

public static class RandomNumberGeneratorExtensions
{
    /// <summary>
    /// 返回指定范围内的非负加密安全随机整数。
    /// </summary>
    /// <param name="minValue">返回的随机数的包含下界。</param>
    /// <param name="maxValue">
    /// 返回的随机数的排除上界。<paramref name="maxValue"/> 必须大于或等于 <paramref name="minValue"/>。
    /// </param>
    /// <returns>指定范围内的加密随机数。</returns>
    /// <remarks>
    /// <para>
    /// 摘自 <see
    /// href="https://docs.microsoft.com/en-us/archive/msdn-magazine/2007/september/net-matters-tales-from-the-cryptorandom"/>。
    /// </para>
    /// </remarks>
    public static int Next(this RandomNumberGenerator randomNumberGenerator, int minValue, int maxValue)
    {
        ArgumentOutOfRangeException.ThrowIfGreaterThan(minValue, maxValue);
        if (minValue == maxValue) return minValue;

        var diff = (long)maxValue - minValue;
        var uint32Buffer = new byte[4];

        while (true)
        {
            randomNumberGenerator.GetBytes(uint32Buffer);
            var rand = BitConverter.ToUInt32(uint32Buffer, 0);

            const long max = 1 + (long)uint.MaxValue;
            var remainder = max % diff;
            if (rand < max - remainder)
            {
                return (int)(minValue + (rand % diff));
            }
        }
    }
}
